package cn.bjxy.shishaolong.system.interceptor;

import cn.bjxy.shishaolong.common.ResultMsg;
import cn.bjxy.shishaolong.common.StatusCode;
import cn.bjxy.shishaolong.common.SysConst;
import cn.bjxy.shishaolong.system.annotation.Permission;
import cn.bjxy.shishaolong.system.exception.OperatorFailureException;
import cn.bjxy.shishaolong.system.service.IResourcesService;
import cn.bjxy.shishaolong.utils.TokenUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 权限控制拦截器
 *
 * @Author 时少龙
 * @Date 2019-04-16 17:17
 * @Version 1.0
 */
@Slf4j
@Component
public class AuthorizationInterceptor implements HandlerInterceptor {
    @Autowired
    private TokenUtil tokenUtil;
    @Autowired
    private IResourcesService resourcesService;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        try {
            if (!(handler instanceof HandlerMethod)) {   // 其实是对静态资源放行
                return true;
            }
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            // 判断是否带有permission注解  带有此注解的需要权限鉴定，
            Permission permission = method.getAnnotation(Permission.class);
            if (permission == null) {
                return true;  // 没有注解的 直接放行
            }
            String token = request.getHeader(SysConst.RESULT_MAP_TOKEN);
            Integer userId = tokenUtil.getUserId(token);
            if (userId != null)
                request.setAttribute(SysConst.CURRENT_USER_ID, userId);
            //
            String permissionValue = permission.value();
            if ("".equals(permissionValue)) {  // 注解值为 ''，默认只需验证是否登录
                return checkUserLogined(userId, response);
            } else { // 注解为具体的资源key 需要验证用户是否有权限访问该资源
                if (userId == null) {
                    retTokenAuthoFailure(response, StatusCode.TOKEN_AUTHEN_FAILURE, StatusCode.TOKEN_AUTHEN_FAILURE_MSG);
                    return false;
                }
                // 验证权限
                List<String> keyList = resourcesService.queryResourcesKeysByUserId(userId);
                if (keyList == null || keyList.size() == 0) return false; // 用户无任何权限
                // 权限比对
                boolean flag = false;
                for (String key : keyList) {
                    if (permissionValue.equals(key)) {
                        flag = true;
                        return true;
                    }
                }
                if (!false) {
                    retTokenAuthoFailure(response, StatusCode.INSUFFICIENT_PRIVILEGE, StatusCode.INSUFFICIENT_PRIVILEGE_MESSAGE);
                    return true;
                }
            }
            return true;
        } catch (OperatorFailureException ofe) {
            ofe.printStackTrace();
            retTokenAuthoFailure(response, ofe.getCode(), ofe.getMessage());
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            retTokenAuthoFailure(response, StatusCode.SERVER_INNER_ERROR, StatusCode.SERVER_INNER_ERROR_MSG);
            return false;
        }
    }

    private void retTokenAuthoFailure(HttpServletResponse response, int tokenAuthenFailure, String tokenAuthenFailureMsg) {
        retResult(response, ResultMsg.create(tokenAuthenFailure, tokenAuthenFailureMsg));
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }

    /**
     * 判断用户是否登录了
     *
     * @param userId
     * @param response
     * @return
     */
    private boolean checkUserLogined(Integer userId, HttpServletResponse response) {
        if (userId == null) {
            retTokenAuthoFailure(response, StatusCode.UNAUTHORIZED_ERROR, StatusCode.UNAUTHORIZED_ERROR_MSG);
            return false;
        }
        return true;
    }

    /**
     * 给客户端返回
     *
     * @param response
     * @param resultMsg
     */
    private void retResult(HttpServletResponse response, ResultMsg resultMsg) {
        response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
        response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
        try (PrintWriter out = response.getWriter()) {
            JSONObject jsonObject = new JSONObject();
//            Object json = JSONObject.toJSON(resultMsg);
            jsonObject.put("code", resultMsg.getCode());
            jsonObject.put("msg", resultMsg.getMsg());
            out.println(jsonObject);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
